package cn.ii8080.i8.gateway.server.filter;

import cn.ii8080.i8.gateway.server.util.RedisUtils;
import com.google.code.kaptcha.Producer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import reactor.core.publisher.Mono;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 图像验证码认证过滤
 */
@Component
public class ImageVerifyCodeGatewayFilterFactory extends AbstractGatewayFilterFactory{
    @Autowired
    private RedisUtils redisUtils;
    public static String IMAGE_RANDOM = "captchaRandom";
    public static String VERIFY_CODE = "imageCaptcha";
    public static String VERIFY_CODE_REDIS_KEY = "i8:gateway:verifyCode:%s:%s";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String imageRandom = request.getQueryParams().getFirst(IMAGE_RANDOM);
            String verifyCode = request.getQueryParams().getFirst(VERIFY_CODE);

            if (StringUtils.isNotEmpty(imageRandom) && StringUtils.isEmpty(verifyCode)) {
                System.out.println("获得验证图片:" + imageRandom);
                Producer defaultKaptcha = null;
                Map<Object, Object> kaptchaMap = new HashMap<>();
                Properties properties = new Properties();
                properties.putAll(kaptchaMap);
                Config kaptchaConfig = new Config(properties);
                DefaultKaptcha defaultKaptchatemp = new DefaultKaptcha();
                defaultKaptchatemp.setConfig(kaptchaConfig);
                defaultKaptcha = defaultKaptchatemp;

                String text = defaultKaptcha.createText();
                BufferedImage image = defaultKaptcha.createImage(text);
                String verifyImagePath = String.format(VERIFY_CODE_REDIS_KEY, request.getPath().toString(), imageRandom);
                redisUtils.set(verifyImagePath, text, 60);
                FastByteArrayOutputStream os = new FastByteArrayOutputStream();
                try {
                    ImageIO.write(image, "jpeg", os);
                } catch (IOException e) {
                    //log.error("ImageIO write err", e);
                    return Mono.error(e);
                }
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.OK);
                response.getHeaders().add("Content-Type", "image/jpeg");
                DataBuffer buffer = response.bufferFactory().wrap(os.toByteArray());
                return response.writeWith(Mono.just(buffer));
            } else if (StringUtils.isNotEmpty(verifyCode) && StringUtils.isNotEmpty(imageRandom)) {
                String verifyImagePath = String.format(VERIFY_CODE_REDIS_KEY, request.getPath().toString(), imageRandom);
                Object verifyCode2 = redisUtils.get(verifyImagePath);
                if (ObjectUtils.isNotEmpty(verifyCode2) && verifyCode.equalsIgnoreCase(verifyCode2.toString())) {
                    redisUtils.del(verifyImagePath);
                    return chain.filter(exchange);
                } else {
                    System.out.println("验证失败");
                    ServerHttpResponse response = exchange.getResponse();
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    redisUtils.del(verifyImagePath);
                    return response.setComplete();
                }
            } else {
                System.out.println("无验证码");
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                // response.getHeaders().add("Content-Type", "image/jpeg");
                return response.setComplete();
            }

        };
    }

}
